const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const Admin = require('../models/Admin');
const logger = require('../utils/logger');
const redis = require('../config/redis');

// 缓存键前缀
const CACHE_KEY = {
  ADMIN_INFO: 'admin:info:',
  ADMIN_TOKEN: 'admin:token:'
};

// 缓存时间(秒)
const CACHE_TTL = {
  ADMIN_INFO: 60 * 60, // 1小时
  ADMIN_TOKEN: 60 * 60 * 24 * 7 // 7天
};

// 管理员登录
exports.login = async (req, res) => {
  try {
    logger.info('收到登录请求:', { 
      body: req.body,
      headers: req.headers 
    });
    
    const { username, password } = req.body;
    
    if (!username || !password) {
      logger.warn('用户名或密码为空');
      return res.status(401).json({ message: '用户名和密码不能为空' });
    }

    // 查找管理员
    const admin = await Admin.findOne({ where: { username } });
    
    logger.info('查询管理员结果:', { 
      found: !!admin,
      username,
      adminData: admin ? {
        id: admin.id,
        username: admin.username,
        hasPassword: !!admin.password,
        passwordLength: admin.password ? admin.password.length : 0
      } : null
    });

    if (!admin) {
      logger.warn('用户名不存在:', { username });
      return res.status(401).json({ message: '用户名或密码错误' });
    }

    // 验证密码
    const isValid = await bcrypt.compare(password, admin.password);
    logger.info('密码验证结果:', { 
      isValid,
      inputPassword: password,
      hashedPassword: admin.password
    });

    if (!isValid) {
      logger.warn('密码错误:', { username });
      return res.status(401).json({ message: '用户名或密码错误' });
    }

    // 生成 JWT token
    const token = jwt.sign(
      { id: admin.id, username: admin.username },
      process.env.JWT_SECRET,
      { expiresIn: '24h' }
    );

    logger.info('登录成功，生成 token:', { 
      username,
      token,
      jwtSecret: process.env.JWT_SECRET ? '已设置' : '未设置'
    });

    // 缓存管理员信息
    const adminInfo = {
      id: admin.id,
      username: admin.username,
      role: admin.role,
      last_login: new Date()
    };

    await redis.set(
      `${CACHE_KEY.ADMIN_INFO}${admin.id}`,
      JSON.stringify(adminInfo),
      'EX',
      CACHE_TTL.ADMIN_INFO
    );

    // 缓存token
    await redis.set(
      `${CACHE_KEY.ADMIN_TOKEN}${token}`,
      admin.id,
      'EX',
      CACHE_TTL.ADMIN_TOKEN
    );

    logger.info('管理员登录成功:', {
      id: admin.id,
      username: admin.username
    });

    res.json({
      code: 200,
      data: {
        token,
        admin: adminInfo
      },
      message: '登录成功'
    });
  } catch (error) {
    logger.error('登录失败:', error);
    res.status(500).json({ 
      message: '服务器错误',
      error: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
};

// 修改密码
exports.changePassword = async (req, res) => {
  try {
    const { currentPassword, newPassword } = req.body;
    const adminId = req.admin.id;

    logger.info('修改密码请求:', { 
      adminId,
      hasCurrentPassword: !!currentPassword,
      hasNewPassword: !!newPassword,
      reqAdmin: req.admin
    });

    // 查找管理员
    const admin = await Admin.findByPk(adminId);
    logger.info('查找管理员结果:', { 
      found: !!admin,
      adminData: admin ? {
        id: admin.id,
        username: admin.username,
        hasPassword: !!admin.password
      } : null
    });

    if (!admin) {
      return res.status(404).json({
        code: 404,
        message: '管理员不存在'
      });
    }

    // 验证旧密码
    const isValidPassword = await bcrypt.compare(currentPassword, admin.password);
    logger.info('验证旧密码结果:', { 
      isValid: isValidPassword,
      currentPasswordLength: currentPassword?.length,
      hashedPasswordLength: admin.password?.length
    });

    if (!isValidPassword) {
      return res.status(400).json({
        code: 400,
        message: '旧密码错误'
      });
    }

    // 加密新密码
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(newPassword, salt);
    logger.info('新密码加密完成:', { 
      saltLength: salt.length,
      hashedPasswordLength: hashedPassword.length
    });

    // 更新密码
    await admin.update({ password: hashedPassword });
    logger.info('密码更新成功');

    // 生成新的token
    const token = jwt.sign(
      { id: admin.id, username: admin.username },
      process.env.JWT_SECRET,
      { expiresIn: '24h' }
    );
    logger.info('生成新token成功');

    // 清除管理员信息缓存
    await redis.del(`${CACHE_KEY.ADMIN_INFO}${adminId}`);

    // 清除所有token缓存（强制所有设备重新登录）
    const tokenKeys = await redis.keys(`${CACHE_KEY.ADMIN_TOKEN}*`);
    if (tokenKeys.length > 0) {
      await redis.del(tokenKeys);
    }

    logger.info('管理员修改密码成功:', {
      id: adminId
    });

    res.json({
      code: 200,
      data: {
        token,
        needRelogin: true
      },
      message: '密码修改成功，请重新登录'
    });
  } catch (error) {
    logger.error('修改密码失败:', {
      error: error.message,
      stack: error.stack,
      reqBody: req.body,
      reqAdmin: req.admin
    });
    res.status(500).json({
      code: 500,
      message: '修改密码失败',
      error: process.env.NODE_ENV === 'development' ? error.message : undefined
    });
  }
};

// 获取管理员信息
exports.getInfo = async (req, res) => {
  try {
    const adminId = req.admin.id;

    // 尝试从缓存获取
    const cacheKey = `${CACHE_KEY.ADMIN_INFO}${adminId}`;
    const cachedData = await redis.get(cacheKey);
    if (cachedData) {
      logger.info('从缓存获取管理员信息');
      return res.json(JSON.parse(cachedData));
    }

    // 从数据库获取
    const admin = await Admin.findByPk(adminId);
    if (!admin) {
      return res.status(404).json({ message: '管理员不存在' });
    }

    const adminInfo = {
      id: admin.id,
      username: admin.username,
      role: admin.role,
      last_login: admin.last_login
    };

    // 设置缓存
    await redis.set(cacheKey, JSON.stringify(adminInfo), 'EX', CACHE_TTL.ADMIN_INFO);
    logger.info('管理员信息已缓存');

    res.json(adminInfo);
  } catch (error) {
    logger.error('获取管理员信息失败:', error);
    res.status(500).json({ message: '获取信息失败' });
  }
};

// 退出登录
exports.logout = async (req, res) => {
  try {
    const adminId = req.admin.id;
    const token = req.token;

    // 清除管理员信息缓存
    await redis.del(`${CACHE_KEY.ADMIN_INFO}${adminId}`);
    // 清除token缓存
    await redis.del(`${CACHE_KEY.ADMIN_TOKEN}${token}`);

    logger.info('管理员登出成功:', {
      id: adminId,
      token
    });

    res.json({ message: '登出成功' });
  } catch (error) {
    logger.error('登出失败:', error);
    res.status(500).json({ message: '登出失败' });
  }
}; 